import logging
import os
from enum import Enum

import MySQLdb
import paramiko
import redis
from django.contrib import messages
from django.core.cache import cache

from .settings import settings_p1, settings_p2, settings_p3, settings_p4


def get_influx_env(pid):
    if pid == '1':
        return settings_p1.InfluxConfig.env()
    if pid == '2':
        return settings_p2.InfluxConfig.env()
    if pid == '3':
        return settings_p3.InfluxConfig.env()
    if pid == '4':
        return settings_p4.InfluxConfig.env()


def log():
    return logging.getLogger('django')


def extend_user_expire():
    cache.set('login-user', cache.get('login-user'), 60 * 30)


def get_dir():
    base_dir = str(os.path.dirname(__file__))
    return base_dir.replace('\\', '/')


def get_env():
    env = cache.get('env')
    if env is None:
        env = 'dev'
    return env


def get_log_name():
    pid = cache.get('pid')
    if pid is None:
        pid = '1'
    return 'p{}.log'.format(pid)


def get_mysql_dev():
    return settings_p1.MysqlConfig.env()


def get_redis_env():
    return settings_p1.RedisConfig.env()


def get_settings_file(pid):
    return '{}/settings/settings_p{}.py'.format(get_dir(), pid)


def mod_settings_env(pid, env):
    """替换文件中的字符串，首次遇到的，即最开始几行
    """
    env = STA.get_env(env)
    file = get_settings_file(pid)
    prefix = 'EXEC_ENV'
    file_data = ""
    row_num = 0
    with open(file, "r", encoding="utf-8") as f:
        for line in f:
            row_num += 1
            if row_num in range(1, 10) and prefix in line:
                line = "{} = '{}'\n".format(prefix, env)
            file_data += line
    with open(file, "w", encoding="utf-8") as f:
        f.write(file_data)


def set_user(request, obj):
    """操作用户信息"""
    user_id = request.user.id
    if obj.id is None:
        obj.create_user_id = user_id
    obj.update_user_id = user_id


def err_msg(request, msg):
    """提示错误信息"""
    messages.error(request, 'Error：{}!'.format(msg))
    messages.set_level(request, messages.ERROR)
    return None


def print_info(msg):
    """打印信息"""
    print("< {} >".format(msg).center(80, "="))
    print('')


class MysqlUtil:
    """mysql工具类"""
    conn = None
    host = '192.168.18.13'
    port = '3306'
    db = 'db_common'
    user = 'root'
    pwd = 'root'

    @classmethod
    def init_dev(cls):
        try:
            # 初始化数据库连接
            cls.conn = MySQLdb.connect(
                host=cls.host,
                port=int(cls.port),
                user=cls.user,
                password=cls.pwd,
                db=cls.db,
            )
        except():
            print("mysql init failed, please check the config")

    @classmethod
    def set_run_env(cls, pid, env):
        """获取运行环境"""
        cls.init_dev()
        sql = 'UPDATE django_mid_main_project set env_run = {} where id = {}'.format(env, pid)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def set_env_by_port(cls, port):
        """根据端口重置运行环境状态"""
        cls.init_dev()
        sql = 'UPDATE django_mid_main_project set env_run = 0 where port = {}'.format(port)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def get_run_env(cls, pid):
        """获取运行环境"""
        cls.init_dev()
        sql = 'SELECT env_run FROM django_mid_main_project where id = {}'.format(pid)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchone()
            if res is not None:
                return res[0]
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def get_id_port(cls):
        """获取工程编号"""
        ret = {}
        cls.init_dev()
        sql = 'SELECT port, env_run FROM django_mid_main_project where id != 1 and env_run != 0'
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchall()
            for tup in res:
                ret[tup[0]] = tup[1]
            return ret
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def get_port(cls, pid):
        """获取工程编号"""
        cls.init_dev()
        sql = 'SELECT port FROM django_mid_main_project where id = {}'.format(pid)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchone()
            if res is not None:
                return res[0]
            else:
                return None
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def get_ps(cls, pid=None):
        """获取工程编号"""
        cls.init_dev()
        if pid is None:
            pid = cache.get('pid')
            if pid is None:
                pid = 1
        sql = 'SELECT ps FROM django_mid_main_project where id = {}'.format(pid)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchone()
            if res is not None:
                return res[0]
            else:
                return None
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def exist_env(cls, pid, env):
        """判断执行环境是否可用"""
        cls.init_dev()
        sql = 'SELECT es FROM django_mid_main_project where id = {}'.format(pid)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchone()
            if res is not None:
                es = res[0]
                return STA.get_env(env) in es.split(',')
            else:
                return False
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()

    @classmethod
    def get_pid_by_port(cls, port):
        cls.init_dev()
        sql = 'SELECT id FROM django_mid_main_project where port = {}'.format(port)
        cursor = cls.conn.cursor()
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交修改
            cls.conn.commit()
            res = cursor.fetchone()
            if res is not None:
                return res[0]
            else:
                return None
        except():
            # 发生错误时回滚
            cls.conn.rollback()
        # 关闭连接
        cls.conn.close()


class RedisUtil:
    """redis工具类"""
    pool = None
    prefix = None

    @classmethod
    def init(cls):
        try:
            if cls.pool is None:
                cls.prefix = MysqlUtil.get_ps(1) + ':django:1:run:'
                redis_env = get_redis_env()
                cls.pool = redis.ConnectionPool(
                    host=redis_env.host,
                    port=redis_env.port,
                    password=redis_env.pwd,
                    # True写入value中为str类型，False为字节型
                    decode_responses=True,
                    db=redis_env.db
                )
        except():
            print("redis pool init failed, please check the config")

    @classmethod
    def set_env(cls, pid, env):
        cls.init()
        key = cls.prefix + pid
        conn = redis.Redis(connection_pool=cls.pool)
        conn.set(key, env, ex=300)

    @classmethod
    def get(cls, key):
        cls.init()
        conn = redis.Redis(connection_pool=cls.pool)
        conn.get(cls.prefix + key)

    @classmethod
    def keys(cls):
        cls.init()
        conn = redis.Redis(connection_pool=cls.pool)
        key_pattern = '*{}*'.format(cls.prefix)
        return conn.keys(key_pattern)


class InfluxUtil:
    """influxdb工具类-基于shell脚本"""
    ssh_client = paramiko.SSHClient()

    @classmethod
    def init(cls):
        try:
            pid = cache.get('pid')
            influx_env = get_influx_env(pid)
            cls.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            cls.ssh_client.connect(
                hostname=influx_env.host,
                username=influx_env.sh_user,
                password=influx_env.sh_pwd
            )
        except():
            print("paramiko init failed, please check the config")

    @classmethod
    def exec(cls, cmd):
        """删除测点数据总条数
        :param cmd 组装好的cmd
        """
        cls.init()
        res = 0
        print("cmd: {}".format(cmd))
        stdin, stdout, stderr = cls.ssh_client.exec_command(cmd)
        result = stdout.read()
        ret = result.decode('utf-8').replace('\n', '')
        if len(ret) != 0:
            res = ret
        cls.ssh_client.close()
        return res


class PTN:
    """【字符常量】"""
    COMMA = ','
    AND = 'and'
    OR = 'or'
    EQ = '='
    GTE = '>='
    LTE = '<='
    LP = '('
    RP = ')'
    EPT = ''
    PA = 'and ('
    PO = 'or ('
    SY = ' -y'
    TM = 'time'
    RYB = 'raw_yb'
    MYB = 'mean_yb'
    PID = 'projectId'
    TID = 'typeId'
    SC = 'serialNumbers'
    QA = 'quotaAmount'
    MIV = 'minValue'
    MAV = 'maxValue'
    ITL = 'interval'
    DEC = 'decimal'


class STA(Enum):
    """【状态信息】"""
    OFFLINE = (-1, '离线')
    ONLINE = (0, '在线')
    RED = (1, '红色预警')
    YELLOW = (2, '黄色预警')
    BLUE = (3, '蓝色预警')
    STOPPED = (0, '-')
    DEV = (1, 'dev')
    TEST = (2, 'test')
    PROD = (3, 'prod')
    NO = (0, '否')
    YES = (1, '是')

    @property
    def level(self):
        """获取预警等级"""
        return self.value[0]

    @property
    def name(self):
        """获取预警名称"""
        return self.value[1]

    @classmethod
    def sta(cls, level):
        """根据预警等级获取预警名称"""
        if cls.OFFLINE.level == level:
            return cls.OFFLINE.name
        elif cls.ONLINE.level == level:
            return cls.ONLINE.name
        elif cls.RED.level == level:
            return cls.RED.name
        elif cls.YELLOW.level == level:
            return cls.YELLOW.name
        elif cls.BLUE.level == level:
            return cls.BLUE.name

    @classmethod
    def env(cls, name):
        """根据执行环境tag获取编号"""
        if cls.DEV.name == name:
            return cls.DEV.level
        elif cls.TEST.name == name:
            return cls.TEST.level
        elif cls.PROD.name == name:
            return cls.PROD.level

    @classmethod
    def get_env(cls, level):
        """根据执行环境tag获取编号"""
        level = int(level)
        if cls.DEV.level == level:
            return cls.DEV.name
        elif cls.TEST.level == level:
            return cls.TEST.name
        elif cls.PROD.level == level:
            return cls.PROD.name
